package com.tuyrt.`as`.proj.main.fragment.category

import android.graphics.Color
import android.os.Bundle
import android.text.TextUtils
import android.util.SparseIntArray
import android.view.View
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup
import com.alibaba.android.arouter.launcher.ARouter
import com.tuyrt.`as`.proj.common.ui.component.HiBaseFragment
import com.tuyrt.`as`.proj.common.ui.view.loadUrl
import com.tuyrt.`as`.proj.main.R
import com.tuyrt.`as`.proj.main.http.ApiFactory
import com.tuyrt.`as`.proj.main.http.api.CategoryApi
import com.tuyrt.`as`.proj.main.model.Subcategory
import com.tuyrt.`as`.proj.main.model.TabCategory
import com.tuyrt.`as`.proj.main.route.HiRoute
import com.tuyrt.`as`.proj.main.route.HiRoute.Destination.GOODS_LIST
import com.tuyrt.hi.library.restful.HiCallback
import com.tuyrt.hi.library.restful.HiResponse
import com.tuyrt.hi.ui.empty.EmptyView
import com.tuyrt.hi.ui.tab.bottom.HiTabBottomLayout
import kotlinx.android.synthetic.main.fragment_category.*

/**
 * author: Administrator on 2021/4/29.
 * desc:
 */
class CategoryFragment : HiBaseFragment() {

    // 分类内容区域的列数
    private val SPAN_COUNT: Int = 3
    private var emptyView: EmptyView? = null

    private val subcategoryListCache = mutableMapOf<String, List<Subcategory>>()

    override fun getLayoutId(): Int = R.layout.fragment_category


    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        HiTabBottomLayout.clipBottomPadding(root_container)

        content_loading.visibility = View.VISIBLE
        queryCategoryList()
    }

    private fun queryCategoryList() {
        ApiFactory.create(CategoryApi::class.java)
            .queryCategoryList()
            .enqueue(object : HiCallback<List<TabCategory>> {

                override fun onSuccess(response: HiResponse<List<TabCategory>>) {
                    if (response.successful() && response.data != null) {
                        onQueryCategoryListSuccess(response.data!!)
                    }
                }

                override fun onFailed(throwable: Throwable) {
                    showEmptyView()
                }
            })

    }

    private fun onQueryCategoryListSuccess(data: List<TabCategory>) {
        if (!isAlive) return
        emptyView?.visibility = View.GONE
        slider_view?.visibility = View.VISIBLE
        content_loading.visibility = View.GONE

        slider_view.bindMenuView(itemCount = data.size, onBindView = { hiViewHolder, position ->
            val category = data[position]
            hiViewHolder.findViewById<TextView>(R.id.menu_item_title)?.text = category.categoryName
        }, onItemClick = { hiViewHolder, position ->
            val category = data[position]
            val categoryId = category.categoryId
            if (subcategoryListCache.containsKey(categoryId)) {
                onQuerySubcategoryListSuccess(subcategoryListCache[categoryId]!!)
            } else {
                querySubcategoryList(categoryId)
            }

        })
    }

    private fun querySubcategoryList(categoryId: String) {
        ApiFactory.create(CategoryApi::class.java)
            .querySubcategoryList(categoryId)
            .enqueue(object : HiCallback<List<Subcategory>> {
                override fun onSuccess(response: HiResponse<List<Subcategory>>) {
                    if (response.successful() && response.data != null) {
                        onQuerySubcategoryListSuccess(response.data!!)

                        if (!subcategoryListCache.containsKey(categoryId)) {
                            subcategoryListCache[categoryId] = response.data!!
                        }
                    }
                }

                override fun onFailed(throwable: Throwable) {
                }
            })
    }

    private val layoutManager = GridLayoutManager(context, SPAN_COUNT)

    // 组偏移量记录： key=position ,value=之前所有组最后一个item 的 偏移量offset之和
    private val groupSpanSizeOffset = SparseIntArray()
    private val spanSizeLookup = object : SpanSizeLookup() {
        override fun getSpanSize(position: Int): Int {
            var spanSize = 1
            val groupName = subcategoryList[position].groupName
            val nextGroupName = if (position + 1 < subcategoryList.size) subcategoryList[position + 1].groupName else null

            if (TextUtils.equals(groupName, nextGroupName)) {
                spanSize = 1
            } else {
                // 当前位置和下一个位置不再同一个分组
                // 1. 要拿到当前组 position （所在组） 在 groupSpanSizeOffset 的索引下标
                // 2. 拿到 当前组前面一组 存储的 spanSizeOffset 偏移量
                // 3. 给当前组最后一个item 分配 spanSize count
                val groupIndex = groupSpanSizeOffset.indexOfKey(position)
                val size = groupSpanSizeOffset.size()
                val lastGroupOffset = if (size <= 0) 0
                else if (groupIndex >= 0) {
                    // 说明当前组的偏移量记录，已经存在了 groupSpanSizeOffset， 这个情况发生在上下滑动
                    if (groupIndex == 0) 0 else groupSpanSizeOffset.valueAt(groupIndex - 1)
                } else {
                    // 说明当前组的偏移量记录，还没有存在 groupSpanSizeOffset， 这个情况发生在第一次布局的时候
                    // 得到前面所有组的偏移量之和
                    groupSpanSizeOffset.valueAt(size - 1)
                }

                // 计算：计算当前组最后一个item 处于第几列: (position + lastGroupOffset) % SPAN_COUNT
                // 当处于第1列时，spanSize = 3
                // 当处于第2列时，spanSize = 2
                // 当处于第3列时，spanSize = 1
                spanSize = SPAN_COUNT - (position + lastGroupOffset) % SPAN_COUNT
                if (groupIndex < 0) {
                    // 得到当前组和 前面所有组的 spanSize 偏移量之和
                    val groupOffset = lastGroupOffset + spanSize - 1
                    groupSpanSizeOffset.put(position, groupOffset)
                }
            }
            return spanSize
        }
    }

    private val subcategoryList = mutableListOf<Subcategory>()
    private val decoration = CategoryItemDecoration(SPAN_COUNT) { position ->
        subcategoryList[position].groupName
    }

    private fun onQuerySubcategoryListSuccess(data: List<Subcategory>) {
        if (!isAlive) return
        groupSpanSizeOffset.clear()

        subcategoryList.clear()
        subcategoryList.addAll(data)

        if (layoutManager.spanSizeLookup != spanSizeLookup) {
            layoutManager.spanSizeLookup = spanSizeLookup
        }

        slider_view.bindContentView(
            itemCount = data.size,
            itemDecoration = decoration,
            layoutManager = layoutManager,
            onBindView = { holder, position ->
                val subcategory = data[position]
                holder.findViewById<ImageView>(R.id.content_item_image)?.loadUrl(subcategory.subcategoryIcon)
                holder.findViewById<TextView>(R.id.content_item_title)?.text = subcategory.subcategoryName
            }, onItemClick = { holder, position ->
                // 跳转到类目的商品列表页
                val subcategory = data[position]

                val bundle = Bundle()
                bundle.putString("categoryId", subcategory.categoryId)
                bundle.putString("subcategoryId", subcategory.subcategoryId)
                bundle.putString("categoryTitle", subcategory.subcategoryName)
                HiRoute.startActivity(context!!, bundle, GOODS_LIST)
            })
    }

    private fun showEmptyView() {
        if (!isAlive) return

        if (emptyView == null) {
            emptyView = EmptyView(context!!)
            emptyView?.setIcon(R.string.if_empty)
            emptyView?.setDesc(getString(R.string.list_empty_desc))
            emptyView?.setButton(getString(R.string.list_empty_action), View.OnClickListener {
                queryCategoryList()
            })

            emptyView?.setBackgroundColor(Color.WHITE)
            emptyView?.layoutParams =
                LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)
            root_container.addView(emptyView)
        }

        slider_view.visibility = View.GONE
        emptyView!!.visibility = View.VISIBLE
        content_loading.visibility = View.GONE
    }

}